<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>WT vs WS</title>
  </head>
  <body>
    <p>WebTransport status: <span id="wtStatus">Disconnected</span></p>
    <p>WebSocket status: <span id="wsStatus">Disconnected</span></p>

    <p>WT gameState count and index: <span id="wtGameStateInfo">-</span></p>
    <p>WS gameState count and index: <span id="wsGameStateInfo">-</span></p>

    <script>
      let wtUnreliableGameStateCount = 0;
      let wsGameStateCount = 0;

      const $wtStatus = document.getElementById("wtStatus");
      const $wsStatus = document.getElementById("wsStatus");
      const $wtGameStateInfo = document.getElementById("wtGameStateInfo");
      const $wsGameStateInfo = document.getElementById("wsGameStateInfo");

      class WebTransportClient {
        constructor(transport) {
          this.datagramsReader = transport.datagrams.readable.getReader();
          this.datagramsWriter = transport.datagrams.writable.getWriter();

          this.datagramDataToSend = [];

          this.readData('unreliable');
        }

        binArrayToJson(binArray) {
          let str = "";
          for (let i = 0; i < binArray.length; i++) {
            str += String.fromCharCode(parseInt(binArray[i]));
          }
          return JSON.parse(str)
        }

        jsonToBinArray(json) {
          const str = JSON.stringify(json, null, 0);
          const ret = new Uint8Array(str.length);
          for (let i = 0; i < str.length; i++) {
            ret[i] = str.charCodeAt(i);
          }
          return ret
        }

        async writeData(streamType, data) {
          const writer = this.datagramsWriter;

          try {
            if (writer) {
              await writer.write(data);
            } 
          } catch (err) {
            console.error('Write data error:', err);
          }
        }
      
        async readData(streamType) {
          const streamReader = sthis.datagramsReader;

          if (streamReader) {
            let isOpen = true;

            streamReader.closed
              .catch((e) => console.error("Failed to close", e.toString()))
              .finally(() => isOpen = false);

            while (isOpen) {
              try {
                const { done, value } = await streamReader.read();
                if (done) { break; }
                this.routeData(this.binArrayToJson(value), streamType);
              } catch (e) {
                console.error("Failed to read...", e.toString());
                break;
              }
            }
          }
        }

        routeData(json, streamType) {
          switch (json.msg) {
            case 'gameState':
              wtUnreliableGameStateCount++;
              wtGameStateInfo.innerText = wtUnreliableGameStateCount + ' / ' + json.gameStateIndex;
            break;
          }
        }
      }

      const serverAddress = '23.111.202.19';

      const webTransport = new WebTransport(`https://${serverAddress}:3001`);
      webTransport.ready.then(() => {
        new WebTransportClient(webTransport);
        $wtStatus.innerText = 'Connected';
      });

      const webSocket = new WebSocket(`wss://${serverAddress}:3001`);
      webSocket.onopen = (event) => {
        $wsStatus.innerText = 'Connected';
      };
      webSocket.onerror = (event) => {
        webSocket.close();
      };
      webSocket.onclose = (event) => {
        $wsStatus.innerText = 'Disconnected';
        setTimeout(function() {
          webSocket.connect();
        }, 1000);
      };
      webSocket.onmessage = (event) => {
        const json = JSON.parse(event.data);

        if (json.msg === 'gameState') {
          wsGameStateCount++;
          wsGameStateInfo.innerText = wsGameStateCount + ' / ' + json.gameStateIndex;
        }
      };
      
    </script>
  </body>
</html>